﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Microsoft.SharePoint;
using SPQueryToSql.Extensions;

namespace SPQueryToSql.ApplicationObjects.CAML
{
    internal class In : BaseOperator
    {
        public List<Value> Values;
        public In(XContainer element, IEnumerable<FieldInfo> listFields)
            : base(element, listFields)
        {
            Values = new List<Value>();
            var values = element.Element("Values");
            if (values != null)
            {
                foreach (var value in values.Elements())
                {
                    Values.Add(new Value(value));
                }
            }
        }

        public override string CAMLElementName
        {
            get { return "In"; }
        }

        public override string ToString(int tabQnt)
        {
            var sb = new StringBuilder();
            const string tab = @"    ";
            for (var i = 0; i < tabQnt; i++) sb.Append(tab);
            sb.AppendFormat("<In>{0}{1}", Environment.NewLine, FieldRef.ToString(tabQnt + 1));
            for (var i = 0; i < tabQnt + 1; i++) sb.Append(tab);
            sb.Append(@"<Values>" + Environment.NewLine);
            foreach (var value in Values)
            {
                sb.Append(value.ToString(tabQnt + 2));
            }
            for (var i = 0; i < tabQnt + 1; i++) sb.Append(tab);
            sb.Append(@"</Values>" + Environment.NewLine);
            for (var i = 0; i < tabQnt; i++) sb.Append(tab);
            sb.Append("</In>" + Environment.NewLine);
            return sb.ToString();
        }

        public override string ToSql(Query query)
        {
            var sql = new StringBuilder();
            var vals = string.Join(",",
                                   Values.Select(v => string.Format(FieldInfo.Type.ValueFormat(), v.Text)).ToArray());
            var valsStr = string.Join(",",
                                   Values.Select(v => string.Format(FieldInfo.Type.ValueFormat(), "'"+v.Text+"'")).ToArray());
            switch (FieldInfo.Type)
            {
                case SPFieldType.Invalid:
                case SPFieldType.AllDayEvent:
                    break;
                case SPFieldType.Text:
                    sql.AppendFormat("[{0}] IN {1}", FieldInfo.InternalName, valsStr);
                    break;
                case SPFieldType.Note:
                    sql.AppendFormat("[{0}] IN {1}", FieldInfo.InternalName, valsStr);
                    break;
                case SPFieldType.DateTime:
                    sql.AppendFormat("[{0}] IN {1}", FieldInfo.InternalName, valsStr);
                    break;
                case SPFieldType.Choice:
                    sql.AppendFormat("[{0}] IN {1}", FieldInfo.InternalName, valsStr);
                    break;
                case SPFieldType.URL:
                    sql.AppendFormat("[{0}] IN {1}", FieldInfo.InternalName, valsStr);
                    break;
                case SPFieldType.Integer:
                    sql.AppendFormat("[{0}] IN {1}", FieldInfo.InternalName, vals);
                    break;
                case SPFieldType.Counter:
                    sql.AppendFormat("[{0}] IN {1}", FieldInfo.InternalName, vals);
                    break;
                case SPFieldType.Boolean:
                    sql.AppendFormat("[{0}] = {1}", FieldInfo.InternalName, Value.Text.Equals("TRUE", StringComparison.InvariantCultureIgnoreCase) ? "1" : "0");
                    break;
                case SPFieldType.Number:
                    sql.AppendFormat("[{0}] IN {1}", FieldInfo.InternalName, vals);
                    break;
                case SPFieldType.Currency:
                    sql.AppendFormat("[{0}] IN {1}", FieldInfo.InternalName, vals);
                    break;
                case SPFieldType.Attachments:
                    break;
                case SPFieldType.MaxItems:
                    sql.AppendFormat("[{0}] IN {1}", FieldInfo.InternalName, vals);
                    break;
                case SPFieldType.ModStat:

                    break;
                case SPFieldType.Lookup:
                    if (FieldRef.LookupId == true)
                    {
                        sql.AppendFormat(
                            FieldInfo.IsMulti ? "[{0}] LIKE '%;#%{1}%;#%;#%'" : "[{0}] LIKE ';#%{1}%;#%;#'",
                            FieldInfo.InternalName, Value.Text);
                    }
                    else
                    {
                        sql.AppendFormat(
                            FieldInfo.IsMulti ? "[{0}] LIKE '%;#%[0-9]%;#{1};#%'" : "[{0}] LIKE ';#%[0-9]%;#{1};#'",
                            FieldInfo.InternalName, Value.Text);
                    }
                    break;
                case SPFieldType.Computed:
                    sql.AppendFormat("[{0}] IN {1}", FieldInfo.InternalName, valsStr);
                    break;
                case SPFieldType.MultiChoice:
                    sql.AppendFormat("[{0}] LIKE '%;#%{1}%;#%'", FieldInfo.InternalName, Value.Text);
                    break;
                case SPFieldType.Calculated:
                    sql.AppendFormat("[{0}] IN {1}", FieldInfo.InternalName, valsStr);
                    break;
                case SPFieldType.User:
                    if (FieldRef.LookupId == true)
                    {
                        sql.AppendFormat(
                            FieldInfo.IsMulti ? "[{0}] NOT LIKE '%;#%{1}%;#%;#%'" : "[{0}] LIKE '%{1};#%'",
                            FieldInfo.InternalName, Value.Text);
                    }
                    else
                    {
                        sql.AppendFormat(
                            FieldInfo.IsMulti ? "[{0}] NOT IKE '%;#%[0-9]%;#{1};#%'" : "[{0}] LIKE '[0-9]%;#{1}'",
                            FieldInfo.InternalName, Value.Text);
                    }
                    break;
                default:
                    sql.Append("1=1");
                    break;
            }
            return sql.ToString();
                //sql.AppendFormat(SqlPredicateFormat, FieldInfo.InternalName, );
        }
    }
}
